use async_trait::async_trait;
use rustcloud_core::{ServiceResult, ServiceError};
use crate::tracing::{TraceExporter, Span, Trace, SpanKind, SpanStatus};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;

/// Jaeger Span格式
#[derive(Debug, Clone, Serialize, Deserialize)]
struct JaegerSpan {
    #[serde(rename = "traceID")]
    trace_id: String,
    #[serde(rename = "spanID")]
    span_id: String,
    #[serde(rename = "parentSpanID", skip_serializing_if = "Option::is_none")]
    parent_span_id: Option<String>,
    #[serde(rename = "operationName")]
    operation_name: String,
    #[serde(rename = "startTime")]
    start_time: u64,
    #[serde(rename = "duration")]
    duration: u64,
    #[serde(rename = "flags")]
    flags: u32,
    #[serde(rename = "logs")]
    logs: Vec<JaegerLog>,
    #[serde(rename = "tags")]
    tags: Vec<JaegerTag>,
    #[serde(rename = "process")]
    process: JaegerProcess,
    #[serde(rename = "references", skip_serializing_if = "Vec::is_empty")]
    references: Vec<JaegerReference>,
}

/// Jaeger标签
#[derive(Debug, Clone, Serialize, Deserialize)]
struct JaegerTag {
    key: String,
    #[serde(rename = "type")]
    tag_type: String,
    value: Value,
}

impl JaegerTag {
    fn string_tag(key: &str, value: &str) -> Self {
        Self {
            key: key.to_string(),
            tag_type: "string".to_string(),
            value: Value::String(value.to_string()),
        }
    }

    fn bool_tag(key: &str, value: bool) -> Self {
        Self {
            key: key.to_string(),
            tag_type: "bool".to_string(),
            value: Value::Bool(value),
        }
    }

    fn number_tag(key: &str, value: f64) -> Self {
        Self {
            key: key.to_string(),
            tag_type: "number".to_string(),
            value: Value::Number(serde_json::Number::from_f64(value).unwrap_or_else(|| serde_json::Number::from(0))),
        }
    }
}

/// Jaeger日志
#[derive(Debug, Clone, Serialize, Deserialize)]
struct JaegerLog {
    timestamp: u64,
    fields: Vec<JaegerTag>,
}

/// Jaeger进程信息
#[derive(Debug, Clone, Serialize, Deserialize)]
struct JaegerProcess {
    #[serde(rename = "serviceName")]
    service_name: String,
    tags: Vec<JaegerTag>,
}

/// Jaeger引用
#[derive(Debug, Clone, Serialize, Deserialize)]
struct JaegerReference {
    #[serde(rename = "refType")]
    ref_type: String,
    #[serde(rename = "traceID")]
    trace_id: String,
    #[serde(rename = "spanID")]
    span_id: String,
}

/// Jaeger批次
#[derive(Debug, Clone, Serialize, Deserialize)]
struct JaegerBatch {
    spans: Vec<JaegerSpan>,
    process: JaegerProcess,
}

/// Jaeger追踪导出器配置
#[derive(Debug, Clone)]
pub struct JaegerExporterConfig {
    /// Jaeger代理地址
    pub agent_endpoint: String,
    /// 服务名称
    pub service_name: String,
    /// 服务版本
    pub service_version: String,
    /// 环境名称
    pub environment: String,
    /// 最大批次大小
    pub max_batch_size: usize,
    /// 批次超时时间（毫秒）
    pub batch_timeout_ms: u64,
    /// 启用压缩
    pub compression_enabled: bool,
}

impl Default for JaegerExporterConfig {
    fn default() -> Self {
        Self {
            agent_endpoint: "http://localhost:14268/api/traces".to_string(),
            service_name: "rustcloud-service".to_string(),
            service_version: "1.0.0".to_string(),
            environment: "development".to_string(),
            max_batch_size: 100,
            batch_timeout_ms: 5000,
            compression_enabled: false,
        }
    }
}

/// Jaeger追踪导出器
pub struct JaegerTraceExporter {
    config: JaegerExporterConfig,
    client: reqwest::Client,
    batch_buffer: Arc<RwLock<Vec<JaegerSpan>>>,
}

impl JaegerTraceExporter {
    pub fn new(config: JaegerExporterConfig) -> Self {
        let client = reqwest::Client::new();
        
        Self {
            config,
            client,
            batch_buffer: Arc::new(RwLock::new(Vec::new())),
        }
    }

    /// 将内部Span转换为Jaeger格式
    fn convert_span_to_jaeger(&self, span: Span) -> JaegerSpan {
        let mut tags = vec![
            JaegerTag::string_tag("span.kind", &self.span_kind_to_string(&span.kind)),
            JaegerTag::string_tag("resource.name", &span.resource),
        ];

        // 转换自定义标签
        for (key, value) in span.attributes.tags {
            tags.push(JaegerTag::string_tag(&key, &value));
        }

        // 添加状态标签
        match span.attributes.status {
            SpanStatus::Ok => tags.push(JaegerTag::bool_tag("error", false)),
            SpanStatus::Error => {
                tags.push(JaegerTag::bool_tag("error", true));
                if let Some(message) = span.attributes.status_message {
                    tags.push(JaegerTag::string_tag("error.message", &message));
                }
            },
            SpanStatus::Unset => {}
        }

        // 转换日志
        let logs: Vec<JaegerLog> = span.attributes.logs.into_iter().map(|log| {
            let mut fields = vec![
                JaegerTag::string_tag("level", &log.level),
                JaegerTag::string_tag("message", &log.message),
            ];
            
            for (key, value) in log.fields {
                fields.push(JaegerTag::string_tag(&key, &value));
            }
            
            JaegerLog {
                timestamp: log.timestamp,
                fields,
            }
        }).collect();

        // 转换引用
        let references: Vec<JaegerReference> = span.references.into_iter().map(|ref_| {
            JaegerReference {
                ref_type: match ref_.reference_type {
                    crate::tracing::SpanReferenceType::ChildOf => "CHILD_OF".to_string(),
                    crate::tracing::SpanReferenceType::FollowsFrom => "FOLLOWS_FROM".to_string(),
                },
                trace_id: ref_.trace_id,
                span_id: ref_.span_id,
            }
        }).collect();

        // 创建进程信息
        let process = JaegerProcess {
            service_name: span.service_name.clone(),
            tags: vec![
                JaegerTag::string_tag("service.version", &self.config.service_version),
                JaegerTag::string_tag("environment", &self.config.environment),
                JaegerTag::string_tag("jaeger.version", "rustcloud-1.0.0"),
            ],
        };

        JaegerSpan {
            trace_id: self.format_trace_id(&span.trace_id),
            span_id: self.format_span_id(&span.span_id),
            parent_span_id: span.parent_id.map(|id| self.format_span_id(&id)),
            operation_name: span.operation_name,
            start_time: span.start_time,
            duration: span.duration.unwrap_or(0),
            flags: 1, // sampled
            logs,
            tags,
            process,
            references,
        }
    }

    /// 将SpanKind转换为字符串
    fn span_kind_to_string(&self, kind: &SpanKind) -> String {
        match kind {
            SpanKind::Client => "client".to_string(),
            SpanKind::Server => "server".to_string(),
            SpanKind::Producer => "producer".to_string(),
            SpanKind::Consumer => "consumer".to_string(),
            SpanKind::Internal => "internal".to_string(),
        }
    }

    /// 格式化Trace ID为Jaeger格式
    fn format_trace_id(&self, trace_id: &str) -> String {
        // 移除连字符，确保是32位十六进制字符串
        trace_id.replace("-", "").to_lowercase()
    }

    /// 格式化Span ID为Jaeger格式
    fn format_span_id(&self, span_id: &str) -> String {
        // 取前16个字符作为Span ID
        let clean_id = span_id.replace("-", "");
        if clean_id.len() >= 16 {
            clean_id[..16].to_string()
        } else {
            format!("{:0<16}", clean_id)
        }
    }

    /// 发送批次到Jaeger
    async fn send_batch(&self, spans: Vec<JaegerSpan>) -> ServiceResult<()> {
        if spans.is_empty() {
            return Ok(());
        }

        let process = JaegerProcess {
            service_name: self.config.service_name.clone(),
            tags: vec![
                JaegerTag::string_tag("service.version", &self.config.service_version),
                JaegerTag::string_tag("environment", &self.config.environment),
                JaegerTag::string_tag("jaeger.version", "rustcloud-1.0.0"),
            ],
        };

        let batch = JaegerBatch { spans, process };
        
        let mut request = self.client
            .post(&self.config.agent_endpoint)
            .json(&batch);

        if self.config.compression_enabled {
            request = request.header("Content-Encoding", "gzip");
        }

        let response = request
            .send()
            .await
            .map_err(|e| ServiceError::MetricsError(format!("发送Jaeger批次失败: {}", e)))?;

        if !response.status().is_success() {
            let status = response.status();
            let body = response.text().await.unwrap_or_default();
            return Err(ServiceError::MetricsError(format!(
                "Jaeger响应错误 {}: {}", status, body
            )));
        }

        Ok(())
    }

    /// 刷新批次缓冲区
    async fn flush_batch(&self) -> ServiceResult<()> {
        let spans = {
            let mut buffer = self.batch_buffer.write().await;
            buffer.drain(..).collect::<Vec<_>>()
        };

        if !spans.is_empty() {
            self.send_batch(spans).await?;
        }

        Ok(())
    }

    /// 获取批次统计信息
    pub async fn get_batch_stats(&self) -> usize {
        self.batch_buffer.read().await.len()
    }
}

#[async_trait]
impl TraceExporter for JaegerTraceExporter {
    async fn export_spans(&self, spans: Vec<Span>) -> ServiceResult<()> {
        let jaeger_spans: Vec<JaegerSpan> = spans
            .into_iter()
            .map(|span| self.convert_span_to_jaeger(span))
            .collect();

        let mut buffer = self.batch_buffer.write().await;
        buffer.extend(jaeger_spans);

        // 检查是否需要刷新
        if buffer.len() >= self.config.max_batch_size {
            let spans_to_send = buffer.drain(..).collect();
            drop(buffer);
            self.send_batch(spans_to_send).await?;
        }

        Ok(())
    }

    async fn export_trace(&self, trace: Trace) -> ServiceResult<()> {
        // 将Trace的所有Span转换并导出
        self.export_spans(trace.spans).await
    }

    async fn shutdown(&self) -> ServiceResult<()> {
        self.flush_batch().await
    }
}

/// HTTP追踪导出器（通用HTTP端点）
pub struct HttpTraceExporter {
    endpoint: String,
    client: reqwest::Client,
    headers: HashMap<String, String>,
}

impl HttpTraceExporter {
    pub fn new(endpoint: String) -> Self {
        Self {
            endpoint,
            client: reqwest::Client::new(),
            headers: HashMap::new(),
        }
    }

    pub fn with_header(mut self, key: &str, value: &str) -> Self {
        self.headers.insert(key.to_string(), value.to_string());
        self
    }

    pub fn with_auth_token(self, token: &str) -> Self {
        self.with_header("Authorization", &format!("Bearer {}", token))
    }
}

#[async_trait]
impl TraceExporter for HttpTraceExporter {
    async fn export_spans(&self, spans: Vec<Span>) -> ServiceResult<()> {
        let payload = serde_json::to_string(&spans)
            .map_err(|e| ServiceError::MetricsError(format!("序列化Spans失败: {}", e)))?;

        let mut request = self.client
            .post(&self.endpoint)
            .header("Content-Type", "application/json")
            .body(payload);

        for (key, value) in &self.headers {
            request = request.header(key, value);
        }

        let response = request
            .send()
            .await
            .map_err(|e| ServiceError::MetricsError(format!("发送HTTP请求失败: {}", e)))?;

        if !response.status().is_success() {
            let status = response.status();
            let body = response.text().await.unwrap_or_default();
            return Err(ServiceError::MetricsError(format!(
                "HTTP导出失败 {}: {}", status, body
            )));
        }

        Ok(())
    }

    async fn export_trace(&self, trace: Trace) -> ServiceResult<()> {
        let payload = serde_json::to_string(&trace)
            .map_err(|e| ServiceError::MetricsError(format!("序列化Trace失败: {}", e)))?;

        let mut request = self.client
            .post(&self.endpoint)
            .header("Content-Type", "application/json")
            .body(payload);

        for (key, value) in &self.headers {
            request = request.header(key, value);
        }

        let response = request
            .send()
            .await
            .map_err(|e| ServiceError::MetricsError(format!("发送HTTP请求失败: {}", e)))?;

        if !response.status().is_success() {
            let status = response.status();
            let body = response.text().await.unwrap_or_default();
            return Err(ServiceError::MetricsError(format!(
                "HTTP导出失败 {}: {}", status, body
            )));
        }

        Ok(())
    }

    async fn shutdown(&self) -> ServiceResult<()> {
        // HTTP导出器不需要特殊的关闭逻辑
        Ok(())
    }
}

/// 文件追踪导出器
pub struct FileTraceExporter {
    file_path: String,
    buffer: Arc<RwLock<Vec<String>>>,
    max_buffer_size: usize,
}

impl FileTraceExporter {
    pub fn new(file_path: String, max_buffer_size: usize) -> Self {
        Self {
            file_path,
            buffer: Arc::new(RwLock::new(Vec::new())),
            max_buffer_size,
        }
    }

    /// 刷新缓冲区到文件
    async fn flush_to_file(&self) -> ServiceResult<()> {
        let lines = {
            let mut buffer = self.buffer.write().await;
            buffer.drain(..).collect::<Vec<_>>()
        };

        if !lines.is_empty() {
            let content = lines.join("\n") + "\n";
            tokio::fs::write(&self.file_path, content)
                .await
                .map_err(|e| ServiceError::MetricsError(format!("写入文件失败: {}", e)))?;
        }

        Ok(())
    }
}

#[async_trait]
impl TraceExporter for FileTraceExporter {
    async fn export_spans(&self, spans: Vec<Span>) -> ServiceResult<()> {
        let mut buffer = self.buffer.write().await;
        
        for span in spans {
            let json_line = serde_json::to_string(&span)
                .map_err(|e| ServiceError::MetricsError(format!("序列化Span失败: {}", e)))?;
            buffer.push(json_line);
        }

        let should_flush = buffer.len() >= self.max_buffer_size;
        drop(buffer);

        if should_flush {
            self.flush_to_file().await?;
        }

        Ok(())
    }

    async fn export_trace(&self, trace: Trace) -> ServiceResult<()> {
        let mut buffer = self.buffer.write().await;
        
        let json_line = serde_json::to_string(&trace)
            .map_err(|e| ServiceError::MetricsError(format!("序列化Trace失败: {}", e)))?;
        buffer.push(json_line);

        let should_flush = buffer.len() >= self.max_buffer_size;
        drop(buffer);

        if should_flush {
            self.flush_to_file().await?;
        }

        Ok(())
    }

    async fn shutdown(&self) -> ServiceResult<()> {
        self.flush_to_file().await
    }
}